#!/bin/bash

# PowerBank微服务系统部署脚本
# 版本: 1.0.0
# 日期: 2025-01-07

set -e

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 配置变量
PROJECT_NAME="powerbank"
BASE_DIR=$(pwd)
DOCKER_REGISTRY="registry.powerbank.com"
VERSION="1.0.0"
PROFILE="dev"

# 服务列表
SERVICES=(
    "api-gateway:8080"
    "user-center:8001"
    "payment-center:8002"
    "order-center:8003"
    "device-center:8004"
    "finance-center:8005"
    "admin-system:8006"
)

echo -e "${GREEN}=== PowerBank微服务部署脚本 ===${NC}"

# 函数：打印信息
print_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

print_step() {
    echo -e "${BLUE}[STEP]${NC} $1"
}

# 函数：显示帮助信息
show_help() {
    echo "PowerBank微服务部署脚本"
    echo ""
    echo "用法: $0 [选项] [命令]"
    echo ""
    echo "命令:"
    echo "  build          构建所有微服务"
    echo "  start          启动所有微服务"
    echo "  stop           停止所有微服务"
    echo "  restart        重启所有微服务"
    echo "  status         查看服务状态"
    echo "  logs           查看服务日志"
    echo "  clean          清理Docker资源"
    echo "  deploy         完整部署（构建+启动）"
    echo ""
    echo "选项:"
    echo "  -h, --help     显示帮助信息"
    echo "  -v, --version  指定版本号 (默认: $VERSION)"
    echo "  -p, --profile  指定环境 (默认: $PROFILE)"
    echo "  -s, --service  指定单个服务"
    echo ""
    echo "示例:"
    echo "  $0 deploy                    # 完整部署所有服务"
    echo "  $0 build -v 1.0.1           # 构建指定版本"
    echo "  $0 start -s user-center     # 启动单个服务"
    echo "  $0 logs -s api-gateway      # 查看网关日志"
}

# 函数：检查前置条件
check_prerequisites() {
    print_step "检查前置条件..."
    
    # 检查Docker
    if ! command -v docker &> /dev/null; then
        print_error "Docker未安装或不在PATH中"
        exit 1
    fi
    
    # 检查Docker Compose
    if ! command -v docker-compose &> /dev/null; then
        print_error "Docker Compose未安装或不在PATH中"
        exit 1
    fi
    
    # 检查Maven
    if ! command -v mvn &> /dev/null; then
        print_error "Maven未安装或不在PATH中"
        exit 1
    fi
    
    # 检查Java
    if ! command -v java &> /dev/null; then
        print_error "Java未安装或不在PATH中"
        exit 1
    fi
    
    JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | awk -F. '{print $1}')
    if [ "$JAVA_VERSION" -lt 17 ]; then
        print_error "需要JDK 17或更高版本，当前版本: $JAVA_VERSION"
        exit 1
    fi
    
    print_info "前置条件检查通过"
}

# 函数：构建单个微服务
build_service() {
    local service_name=$1
    local service_dir="${BASE_DIR}/${service_name}"
    
    if [ ! -d "$service_dir" ]; then
        print_warning "服务目录不存在: $service_dir"
        return 1
    fi
    
    print_info "构建微服务: $service_name"
    
    # Maven构建
    cd "$service_dir"
    mvn clean package -DskipTests -Dspring.profiles.active="$PROFILE"
    
    if [ $? -ne 0 ]; then
        print_error "Maven构建失败: $service_name"
        return 1
    fi
    
    # Docker构建
    docker build -t "${PROJECT_NAME}-${service_name}:${VERSION}" .
    
    if [ $? -ne 0 ]; then
        print_error "Docker构建失败: $service_name"
        return 1
    fi
    
    # 标记为latest
    docker tag "${PROJECT_NAME}-${service_name}:${VERSION}" "${PROJECT_NAME}-${service_name}:latest"
    
    print_info "✓ 构建完成: $service_name"
    cd "$BASE_DIR"
}

# 函数：构建所有微服务
build_all() {
    print_step "构建所有微服务..."
    
    # 先构建公共模块
    print_info "构建公共模块..."
    cd "${BASE_DIR}/powerbank-common"
    mvn clean install -DskipTests
    cd "$BASE_DIR"
    
    # 构建各个微服务
    for service_info in "${SERVICES[@]}"; do
        service_name=$(echo "$service_info" | cut -d':' -f1)
        build_service "$service_name"
    done
    
    print_info "所有微服务构建完成"
}

# 函数：启动基础设施
start_infrastructure() {
    print_step "启动基础设施服务..."
    
    # 启动MySQL
    if ! docker ps | grep -q mysql; then
        print_info "启动MySQL..."
        docker run -d \
            --name powerbank-mysql \
            -p 3306:3306 \
            -e MYSQL_ROOT_PASSWORD=powerbank123 \
            -e MYSQL_DATABASE=powerbank \
            -v powerbank-mysql-data:/var/lib/mysql \
            mysql:8.0
    fi
    
    # 启动Redis
    if ! docker ps | grep -q redis; then
        print_info "启动Redis..."
        docker run -d \
            --name powerbank-redis \
            -p 6379:6379 \
            -v powerbank-redis-data:/data \
            redis:7.0-alpine
    fi
    
    # 等待数据库启动
    print_info "等待基础设施服务启动..."
    sleep 10
}

# 函数：启动单个微服务
start_service() {
    local service_name=$1
    local service_port=$(get_service_port "$service_name")
    
    if [ -z "$service_port" ]; then
        print_error "未知服务: $service_name"
        return 1
    fi
    
    print_info "启动微服务: $service_name (端口: $service_port)"
    
    # 停止现有容器（如果存在）
    docker stop "${PROJECT_NAME}-${service_name}" 2>/dev/null || true
    docker rm "${PROJECT_NAME}-${service_name}" 2>/dev/null || true
    
    # 启动新容器
    docker run -d \
        --name "${PROJECT_NAME}-${service_name}" \
        --network bridge \
        -p "${service_port}:${service_port}" \
        -e SPRING_PROFILES_ACTIVE="$PROFILE" \
        -e NACOS_SERVER_ADDR="host.docker.internal:8848" \
        -e MYSQL_HOST="host.docker.internal" \
        -e REDIS_HOST="host.docker.internal" \
        -e ROCKETMQ_NAME_SERVER="host.docker.internal:9876" \
        --restart unless-stopped \
        "${PROJECT_NAME}-${service_name}:${VERSION}"
    
    if [ $? -eq 0 ]; then
        print_info "✓ 启动成功: $service_name"
    else
        print_error "✗ 启动失败: $service_name"
        return 1
    fi
}

# 函数：获取服务端口
get_service_port() {
    local service_name=$1
    for service_info in "${SERVICES[@]}"; do
        if [[ "$service_info" == "$service_name:"* ]]; then
            echo "$service_info" | cut -d':' -f2
            return 0
        fi
    done
    return 1
}

# 函数：启动所有微服务
start_all() {
    print_step "启动所有微服务..."
    
    # 启动基础设施
    start_infrastructure
    
    # 按顺序启动微服务
    for service_info in "${SERVICES[@]}"; do
        service_name=$(echo "$service_info" | cut -d':' -f1)
        start_service "$service_name"
        sleep 5  # 等待服务启动
    done
    
    print_info "所有微服务启动完成"
}

# 函数：停止单个微服务
stop_service() {
    local service_name=$1
    
    print_info "停止微服务: $service_name"
    docker stop "${PROJECT_NAME}-${service_name}" 2>/dev/null || true
    docker rm "${PROJECT_NAME}-${service_name}" 2>/dev/null || true
}

# 函数：停止所有微服务
stop_all() {
    print_step "停止所有微服务..."
    
    for service_info in "${SERVICES[@]}"; do
        service_name=$(echo "$service_info" | cut -d':' -f1)
        stop_service "$service_name"
    done
    
    print_info "所有微服务已停止"
}

# 函数：查看服务状态
show_status() {
    print_step "查看服务状态..."
    
    echo -e "${BLUE}=== 基础设施服务 ===${NC}"
    echo "MySQL:    $(docker ps --format 'table {{.Names}}\t{{.Status}}' | grep mysql || echo '未运行')"
    echo "Redis:    $(docker ps --format 'table {{.Names}}\t{{.Status}}' | grep redis || echo '未运行')"
    echo ""
    
    echo -e "${BLUE}=== 微服务状态 ===${NC}"
    printf "%-20s %-15s %-20s %-10s\n" "服务名称" "容器状态" "健康检查" "端口"
    echo "$(printf '%.0s-' {1..70})"
    
    for service_info in "${SERVICES[@]}"; do
        service_name=$(echo "$service_info" | cut -d':' -f1)
        service_port=$(echo "$service_info" | cut -d':' -f2)
        container_name="${PROJECT_NAME}-${service_name}"
        
        # 检查容器状态
        container_status=$(docker ps --format '{{.Status}}' --filter "name=${container_name}" 2>/dev/null || echo "未运行")
        
        # 检查健康状态
        if [[ "$container_status" == *"Up"* ]]; then
            health_status=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:${service_port}/actuator/health" 2>/dev/null || echo "检查失败")
            if [ "$health_status" = "200" ]; then
                health_status="健康"
            else
                health_status="异常"
            fi
        else
            health_status="N/A"
        fi
        
        printf "%-20s %-15s %-20s %-10s\n" "$service_name" "$container_status" "$health_status" "$service_port"
    done
}

# 函数：查看服务日志
show_logs() {
    local service_name=$1
    local lines=${2:-100}
    
    if [ -z "$service_name" ]; then
        print_error "请指定服务名称"
        return 1
    fi
    
    container_name="${PROJECT_NAME}-${service_name}"
    
    if ! docker ps -a --format '{{.Names}}' | grep -q "^${container_name}$"; then
        print_error "容器不存在: $container_name"
        return 1
    fi
    
    print_info "查看 $service_name 最新 $lines 行日志"
    docker logs --tail "$lines" -f "$container_name"
}

# 函数：清理Docker资源
clean_docker() {
    print_step "清理Docker资源..."
    
    # 停止所有微服务
    stop_all
    
    # 删除微服务镜像
    print_info "删除微服务镜像..."
    docker images --format "table {{.Repository}}:{{.Tag}}" | grep "^${PROJECT_NAME}-" | while read image; do
        docker rmi "$image" 2>/dev/null || true
    done
    
    # 清理未使用的资源
    print_info "清理未使用的Docker资源..."
    docker system prune -f
    
    print_info "Docker资源清理完成"
}

# 函数：完整部署
full_deploy() {
    print_step "开始完整部署..."
    
    check_prerequisites
    build_all
    start_all
    
    print_info "等待服务启动完成..."
    sleep 30
    
    show_status
    
    print_info "完整部署完成!"
    print_info "API网关地址: http://localhost:8080"
    print_info "管理后台地址: http://localhost:8006"
}

# 主函数
main() {
    # 解析命令行参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            -h|--help)
                show_help
                exit 0
                ;;
            -v|--version)
                VERSION="$2"
                shift 2
                ;;
            -p|--profile)
                PROFILE="$2"
                shift 2
                ;;
            -s|--service)
                SERVICE="$2"
                shift 2
                ;;
            build)
                COMMAND="build"
                shift
                ;;
            start)
                COMMAND="start"
                shift
                ;;
            stop)
                COMMAND="stop"
                shift
                ;;
            restart)
                COMMAND="restart"
                shift
                ;;
            status)
                COMMAND="status"
                shift
                ;;
            logs)
                COMMAND="logs"
                shift
                ;;
            clean)
                COMMAND="clean"
                shift
                ;;
            deploy)
                COMMAND="deploy"
                shift
                ;;
            *)
                print_error "未知参数: $1"
                show_help
                exit 1
                ;;
        esac
    done
    
    # 执行命令
    case "${COMMAND:-help}" in
        build)
            check_prerequisites
            if [ -n "$SERVICE" ]; then
                build_service "$SERVICE"
            else
                build_all
            fi
            ;;
        start)
            if [ -n "$SERVICE" ]; then
                start_service "$SERVICE"
            else
                start_all
            fi
            ;;
        stop)
            if [ -n "$SERVICE" ]; then
                stop_service "$SERVICE"
            else
                stop_all
            fi
            ;;
        restart)
            if [ -n "$SERVICE" ]; then
                stop_service "$SERVICE"
                sleep 2
                start_service "$SERVICE"
            else
                stop_all
                sleep 5
                start_all
            fi
            ;;
        status)
            show_status
            ;;
        logs)
            show_logs "$SERVICE"
            ;;
        clean)
            clean_docker
            ;;
        deploy)
            full_deploy
            ;;
        help)
            show_help
            ;;
        *)
            print_error "未知命令: $COMMAND"
            show_help
            exit 1
            ;;
    esac
}

# 执行主函数
main "$@"